package code.tools.commponents
{
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Graphics;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.geom.Rectangle;

	/**
	 * 封装绘制九宫格,三宫格 和一些复杂图形的绘制方法
	 * 图素都采用嵌入的方式
	 *
	 * instance.draw(g,w,h,x,y);
	 * @author liangqian
	 */
	public class Scale9Graphics
	{
		/**
		 * 素材自带最后一像素决定是否有背景色
		 */
		private static const TYPE_DRAW_SCALE_9:uint            = 1;
		private static const TYPE_DRAW_SCALE_3_Horizontal:uint = 2;
		private static const TYPE_DRAW_SCALE_3_Vertical:uint   = 3;
		/**
		 * 49 * 27
		 * cornerWidth 3 px
		 */
		[Embed(source = "../assets/Tab_bg_normal_scale3H.png")]
		private static var hTabNSrc:Class;
		/**
		 * 49 * 27
		 * cornerWidth 3 px
		 */
		[Embed(source = "../assets/Tab_bg_hover_scale3H.png")]
		private static var hTabHSrc:Class;
		/** 
		 * cornerWidth 7 px
		 */
		[Embed(source = "../assets/TextButton_bg_scale3H.png")]
		private static var textButtonNSrc:Class;
		/**
		 * cornerWidth 7 px
		 */
		[Embed(source = "../assets/TextButton_bg_hover_scale3H.png")]
		private static var textButtonHSrc:Class;

		/**
		 * 使用一个边角素材绘制整个边框
		 * 默认边角外至少一象素为边线填充
		 * @param bmd
		 * @param cornerWidth
		 * @param cornerHeight
		 */
		private static function addInstance(type:uint ,
											bmdSrc:Class ,
											cornerWidth:int ,
											cornerHeight:int = 0 ,
											bgOffsetX:int = -1 ,
											bgOffsetY:int = -1):Scale9Graphics
		{
			return new Scale9Graphics(type ,
									  Bitmap(new bmdSrc).bitmapData ,
									  cornerWidth ,
									  cornerHeight ,
									  bgOffsetX ,
									  bgOffsetY);
		}


		/**
		 * 49 * 27
		 * cornerWidth 3 px
		 */
		public static const hTabNormalScale3H:Scale9Graphics          = addInstance(TYPE_DRAW_SCALE_3_Horizontal ,
																				   hTabNSrc ,
																				   3)
		/**
		 * 49 * 27
		 * cornerWidth 3 px
		 */
		public static const hTabHoverScale3H:Scale9Graphics           = addInstance(TYPE_DRAW_SCALE_3_Horizontal ,
																				   hTabHSrc ,
																				  3);
		/**
		 * cornerWidth 7 px
		 */
		public static const textButtonBgNormalScale3H:Scale9Graphics = addInstance(TYPE_DRAW_SCALE_3_Horizontal ,
																				   textButtonNSrc ,
																				   7)
		/**
		 * cornerWidth 7 px
		 */
		public static const textButtonBgHoverScale3H:Scale9Graphics  = addInstance(TYPE_DRAW_SCALE_3_Horizontal ,
																				   textButtonHSrc ,
																				   7);

		///////////////////////////////////
		// instance
		///////////////////////////////////
		private var corner:BitmapData;
		private var hLine:BitmapData;
		private var vLine:BitmapData;
		private var bgColor:uint;

		private var source:BitmapData;
		private var _cornerWidth:int;
		private var _cornerHeight:int;
		private var _bgOx:int;
		private var _bgOy:int;

		public function Scale9Graphics(type:uint ,
									   bmd:BitmapData ,
									   cornerWidth:int ,
									   cornerHeight:int ,
									   bgOffsetX:int ,
									   bgOffsetY:int)
		{
			source = bmd;
			_cornerWidth = cornerWidth;
			_cornerHeight = cornerHeight;
			_bgOx = bgOffsetX;
			_bgOy = bgOffsetY;
			switch (type)
			{
				case TYPE_DRAW_SCALE_9:
					scaleDrawMethod = drawScale9;
					break;
				case TYPE_DRAW_SCALE_3_Horizontal:
					scaleDrawMethod = drawScale3Horizontal;
					break;
				case TYPE_DRAW_SCALE_3_Vertical:
					scaleDrawMethod = drawScale3Vertical;
					break;
				default:
					break;
			}
		}
		private var scaleDrawMethod:Function;

		/**
		 *
		 * @param g
		 * @param w
		 * @param h
		 */
		public function draw(g:Graphics , w:int , h:int , x:int = 0 , y:int = 0):void
		{
//			var cost:int = getTimer();
			scaleDrawMethod(g , w , h , x , y);
//			var t:int = getTimer();
//			trace(t,'[Scale9Graphics::draw]: cost: ',t - cost);
		}

		private static const reusableMatrix:Matrix                   = new Matrix;
		/**
		 * 使用一个边角素材绘制整个边框
		 * 默认边角外至少一象素为边线填充
		 * 默认最后一像素决定中心区域填充色
		 */
		private function drawScale9(g:Graphics , cw:int , ch:int , x:int , y:int):void
		{
			if (corner == null)
				initScale9();
			/*bg*/
			if (bgColor&&_bgOx>0)
			{
				g.beginFill(bgColor , (bgColor >>> 24) / 0xff);
				g.drawRect(_bgOx + x , _bgOy + y , cw - _bgOx * 2 , ch - _bgOy * 2);
			}
			const m:Matrix           = reusableMatrix;
			/*边角外直线部分长度/高度*/
			const contentWidth:int   = cw - _cornerWidth * 2;
			const contetneHeight:int = ch - _cornerHeight * 2;
			/*小键盘位置 8*/
			g.lineStyle();
			m.createBox(1 , 1 , 0 , x + _cornerWidth , y);
			g.beginBitmapFill(hLine , m);
			g.drawRect(x + _cornerWidth , y , contentWidth , _cornerHeight);
			/*2*/
			m.createBox(1 , -1 , 0 , x + _cornerWidth , y + ch - hLine.height);
			g.beginBitmapFill(hLine , m);
			g.drawRect(x + _cornerWidth , y + ch - hLine.height , contentWidth , _cornerHeight);
			/*4*/
			m.createBox(1 , 1 , 0 , x , y + _cornerHeight);
			g.beginBitmapFill(vLine , m);
			g.drawRect(x , y + _cornerHeight , _cornerWidth , contetneHeight);
			/*6*/
			m.createBox(-1 , 1 , 0 , x + cw - vLine.width , y + _cornerHeight);
			g.beginBitmapFill(vLine , m);
			g.drawRect(x + cw - vLine.width , y + _cornerHeight , _cornerWidth , contetneHeight);
			/*7*/
			m.createBox(1 , 1 , 0 , x , y);
			g.beginBitmapFill(corner , m , false);
			g.drawRect(x , y , _cornerWidth , _cornerHeight);
			/*9*/
			m.createBox(-1 , 1 , 0 , x + _cornerWidth + contentWidth + _cornerWidth , y);
			g.beginBitmapFill(corner , m , false);
			g.drawRect(x + _cornerWidth + contentWidth , y , _cornerWidth , _cornerHeight);
			/*1*/
			m.createBox(1 , -1 , 0 , x , y + _cornerHeight + contetneHeight + _cornerHeight);
			g.beginBitmapFill(corner , m , false);
			g.drawRect(x , y + _cornerHeight + contetneHeight , _cornerWidth , _cornerHeight);
			/*3*/
			m.createBox(-1 ,
						-1 ,
						0 ,
						x + _cornerWidth + contentWidth + _cornerWidth ,
						y + _cornerHeight + contetneHeight + _cornerHeight);
			g.beginBitmapFill(corner , m , false);
			g.drawRect(x + _cornerWidth + contentWidth ,
					   y + _cornerHeight + contetneHeight ,
					   _cornerWidth ,
					   _cornerHeight);
			g.endFill();
		}
		
		private static const reusablePoint:Point                     = new Point;
		private static const reusableRectangle:Rectangle             = new Rectangle;

		private function initScale9():void
		{
			const sw:int = source.width;
			const sh:int = source.height;
			bgColor = source.getPixel32(sw - 1 , sh - 1);
			const p:Point = reusablePoint;
			p.normalize(0);
			corner = new BitmapData(_cornerWidth , _cornerHeight , source.transparent , 0);
			corner.copyPixels(source , corner.rect , p);
			/*水平 竖直方向的边线*/
			hLine = new BitmapData(sw - _cornerWidth , _cornerHeight , true , 0);
			const rect:Rectangle = reusableRectangle;
			rect.x = _cornerWidth;
			rect.y = 0;
			rect.width = hLine.width;
			rect.height = hLine.height;
			hLine.copyPixels(source , rect , p);
			vLine = new BitmapData(_cornerWidth , sh - _cornerHeight , true , 0);
			rect.x = 0;
			rect.y = _cornerHeight;
			rect.width = vLine.width;
			rect.height = vLine.height;
			vLine.copyPixels(source , rect , p);
		}

		/**
		 * 使用左中右三部分素材绘制整个形状
		 * 中部拉伸填充
		 * 自带内部背景填充
		 * 左中右 → cornerWidth + (source - cornerWidth * 2) + cornerWidth
		 */
		private function drawScale3Horizontal(g:Graphics , cw:int , h:int , x:int , y:int):void
		{
			if (hLine == null)
				initScale3Horizontal();
			const sw:int   = source.width;
			const sh:int   = source.height;
			const m:Matrix = reusableMatrix;
			g.lineStyle();
			/*left*/
			m.createBox(1 , 1 , 0 , x , y);
			g.beginBitmapFill(source , m , false);
			g.drawRect(x , y , _cornerWidth , sh);
			/*center*/
			m.createBox((cw - _cornerWidth * 2) / hLine.width , 1 , 0 , x + _cornerWidth , y);
			g.beginBitmapFill(hLine , m , false , true);
			g.drawRect(x + _cornerWidth , y , cw - _cornerWidth * 2 , sh);
			/*right*/
			m.createBox(1 , 1 , 0 , x + cw - sw , y);
			g.beginBitmapFill(source , m , false);
			g.drawRect(x + cw - _cornerWidth , y , _cornerWidth , sh);
		}

		private function initScale3Horizontal():void
		{
			const sw:int         = source.width;
			const sh:int         = source.height;
			const rect:Rectangle = reusableRectangle;
			rect.x = _cornerWidth;
			rect.y = 0;
			rect.width = sw;
			rect.height = sh;
			const p:Point = reusablePoint;
			p.normalize(0);
			hLine = new BitmapData(sw - _cornerWidth * 2 , sh , true , 0);
			hLine.copyPixels(source , rect , p);
		}

		private function drawScale3Vertical(g:Graphics , w:int , ch:int , x:int , y:int):void
		{
			if (vLine == null)
				initScale3Vertical();
			const sw:int   = source.width;
			const sh:int   = source.height;
			const m:Matrix = reusableMatrix;
			g.lineStyle();
			/*top*/
			m.createBox(1 , 1 , 0 , x , y);
			g.beginBitmapFill(source , m , false);
			g.drawRect(x , y , sw , _cornerHeight);
			/*middle*/
			m.createBox(1 , (ch - _cornerHeight * 2) / vLine.height , 0 , x , y + _cornerHeight);
			g.beginBitmapFill(vLine , m , false , true);
			g.drawRect(x , y + _cornerHeight , sw , ch - _cornerHeight * 2);
			/*bottom*/
			m.createBox(1 , 1 , 0 , x , y + ch - sh);
			g.beginBitmapFill(source , m , false);
			g.drawRect(x , y + ch - _cornerHeight , sw , _cornerHeight);
		}

		private function initScale3Vertical():void
		{
			const sw:int         = source.width;
			const sh:int         = source.height;
			const rect:Rectangle = reusableRectangle;
			rect.x = 0;
			rect.y = _cornerHeight;
			rect.width = sw;
			rect.height = sh;
			const p:Point = reusablePoint;
			p.normalize(0);
			vLine = new BitmapData(sw , sh - _cornerHeight * 2 , true , 0);
			vLine.copyPixels(source , rect , p);
		}
//		menuPatternSrc = null;
//		itemTipPatternSrc = null;
		hTabNSrc = null;
		hTabHSrc = null;
		textButtonNSrc = null;
		textButtonHSrc = null;
//		vScrollBarThumbSrc = null;
//		itemNormalBorderSrc = null;
//		itemHoverBorderSrc = null;
//		numberBgSrc = null;
	}
}
